package me.helllp.bootman.back.config;

import java.nio.charset.Charset;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4;

import me.helllp.bootman.back.utils.LocalSessionFactory;
import me.helllp.bootman.common.convert.EnumsConverterFactory;


/**
 * Spring MVC 配置
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

	/**
	 * 允许跨域的配置
	 */
	@Value("${bootman.cors.url}")
	private String corsUrl;
	
	/**
	 * 进行跨域的相关设置
	 */
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		if("${bootman.cors.url}".equals(corsUrl)){
			corsUrl = "*";
		}
		
		registry.addMapping("/*").allowedOrigins(corsUrl)
			.allowedMethods(
					org.springframework.http.HttpMethod.GET.name(),
					org.springframework.http.HttpMethod.DELETE.name(),
					org.springframework.http.HttpMethod.HEAD.name(),
					org.springframework.http.HttpMethod.OPTIONS.name(),
					org.springframework.http.HttpMethod.PATCH.name(),
					org.springframework.http.HttpMethod.POST.name(),
					org.springframework.http.HttpMethod.PUT.name(),
					org.springframework.http.HttpMethod.TRACE.name());
	}
	
    /**
     * 增加返回信息的处理器
     * <br/>
     * 使用阿里 FastJson 作为JSON MessageConverter 
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter4 converter = new FastJsonHttpMessageConverter4();
        FastJsonConfig config = new FastJsonConfig();

//        SerializerFeature.WriteEnumUsingName
        //	配置JSON的规则
        config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,//保留空的字段
                SerializerFeature.WriteNullStringAsEmpty,//String null -> ""
                SerializerFeature.WriteNullNumberAsZero);//Number null -> 0

        converter.setFastJsonConfig(config);
        converter.setDefaultCharset(Charset.forName("UTF-8"));
        
        //	添加消息转换规则
        converters.add(converter);
    }
    
    /**
     * 增加参数处理机制，处理Enums
     */
    @Override  
    public void addFormatters(FormatterRegistry registry) {  
        registry.addConverterFactory(new EnumsConverterFactory());  
    }
    
    /**
     * 增加公共的错误处理逻辑
     * 
     * @return
     */
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer(){
        return new EmbeddedServletContainerCustomizer(){
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/comm/404"));
                container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/comm/500"));
                container.addErrorPages(new ErrorPage(java.lang.Throwable.class,"/comm/500"));
            }
        };
    }
    
    /**
     * 添加拦截器，为了进行内存清理！
     */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new HandlerInterceptorAdapter() {
			@Override
			public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
					throws Exception {
				return true;
			}

			@Override
			public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
					Exception ex) throws Exception {
				//	避免内存泄漏
				LocalSessionFactory.removeUserId();
				super.afterCompletion(request, response, handler, ex);
			}
		});

	}
}
